<!-- 选人组件 -->
<template>
  <div class="user-selector" :style="{ width }">
    <a-select
      v-bind="$attrs"
      v-model="user"
      :options="options"
      :style="{ width }"
      :loading="loading"
      :multiple="multiple"
      :filter-option="false"
      allow-clear
      allow-search
      @search="handleSearch"
      @change="change"
    />
  </div>
</template>

<script lang="ts" setup>
  import useLoading from '@/hooks/loading';
  import { ref, watch } from 'vue';
  import { getUserList, UserParams, searchUser } from '@/api/user';
  import { UserState } from '@/store/modules/user/types';
  import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
  import { isArray } from '@/utils/is';

  const { loading, setLoading } = useLoading(false);

  const props = defineProps({
    width: {
      type: String,
      default: '100%',
    },
    modelValue: {
      type: String,
      default: '',
    },
    usingName: {
      type: Boolean,
      default: false,
    },
    projectId: {
      type: String,
      default: undefined,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    showUserName: {
      type: Boolean,
      default: false,
    },
  });
  const emit = defineEmits(['update:modelValue', 'change']);

  const options = ref<SelectOptionData[]>([]);
  let originData: UserState[] = [];

  const user = ref<string | string[]>(props.modelValue);
  const initDefaultValue = (v: string) => {
    if (props.multiple) {
      user.value = v ? v.split(',') : [];
    } else {
      user.value = v;
    }
    const paras = isArray(user.value) ? user.value.join(',') : user.value;
    if (paras) {
      const value = props.usingName ? { names: paras } : { ids: paras };
      getUserInfo(value);
    }
  };
  const getUserInfo = async (value: UserParams) => {
    try {
      const { data } = await getUserList(value);
      originData = data || [];
      options.value = handlerOriginData(originData);
      emit('change', getOthersInfo(user.value));
    } catch (error) {
      // handle error
    }
  };
  let initFlag = true;
  watch(
    () => props.modelValue,
    (n) => {
      if (initFlag) {
        initDefaultValue(n);
      }
    },
    { immediate: true }
  );

  // fetch org data
  const searchUsers = async (searchVal: string) => {
    setLoading(true);
    try {
      const { data } = props.projectId
        ? await searchUser(searchVal, props.projectId)
        : await searchUser(searchVal);
      originData = data || [];
      options.value = handlerOriginData(originData);
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log(err);
    } finally {
      setLoading(false);
    }
  };

  const handlerOriginData = (data: UserState[]) => {
    const result = data.map((item) => {
      const val: SelectOptionData = {};
      const { name, userId, username, id } = item;
      // 接口兼容
      const idValue = id || userId;
      val.value = props.usingName ? username : idValue;
      val.label = props.showUserName ? `${username}(${name})` : name;
      return val;
    });
    return result;
  };

  const handleSearch = (val: string) => {
    searchUsers(val);
  };

  const patchMulti = (v: string | string[]): string => {
    if (isArray(v)) {
      return v.join(',');
    }
    return v;
  };

  const change = (
    val:
      | string
      | number
      | Record<string, any>
      | (string | number | Record<string, any>)[]
  ) => {
    initFlag = false;
    emit('update:modelValue', patchMulti(val as string | string[]));
    emit('change', getOthersInfo(val as string | string[]));
  };

  const getOthersInfo = (val: string | string[]) => {
    if (isArray(val)) {
      const res: UserState[] = [];
      val.forEach((v) => {
        const item = originData.find((it) => {
          // 接口兼容
          const idValue = it.id || it.userId;
          return props.usingName ? it.username === v : idValue === v;
        });
        if (item) {
          res.push(item);
        }
      });
      return res;
    }
    return originData.find((it) => {
      // 接口兼容
      const idValue = it.id || it.userId;
      return props.usingName ? it.username === val : idValue === val;
    });
  };
</script>

<script lang="ts">
  export default {
    name: 'UserSelector',
    inheritAttrs: false,
  };
</script>
